李守中
该站已迁往根域名 https://lishouzhong.com
需要注意,迁移后的文章的 url 可能会发生变化。
域名 https://note.lishouzhong.com 下的内容将不再更新,但已有内容会永久保留。

mdadm 软 raid 相关

Table of Contents

1. 创建与销毁 raid

mdadm 命令常用参数:

  • -A, --assemble 激活阵列。
  • -a, --add 添加设备到阵列。
  • -C, --create 新建一个阵列。
  • -C --homehost=<host_name>, 新建阵列时指定主机名。
  • -C --name=<name>, 新建阵列时指定阵列名。
  • -c, --chunk=<size> 指定阵列的块大小。默认 512K。
  • -D, --detail 打印一个或多个阵列设备信息。
  • -f, --fail 将列出的设备标记为故障。
  • -G, --grow 改变阵列大小和形态。
  • -l, --level=<level> 设置阵列级别。
  • -n, --raid-devices=<member> 指定阵列成员信息。
  • -r, --remove 删除列出的设备,设备不可处于活动状态。
  • -S, --stop 停止阵列,释放所有资源。
  • -s, --scan 扫描配置文件或 /proc/mdstat 得到阵列缺失信息。
  • -v, --verbose 显示详细信息。
  • -x, --spare-devices=<number> 指定阵列中热备设备的数量。

1.1. 创建 raid

raid1 创建:

  • 2 个设备分区组 raid1: mdadm --create /dev/md0 --level=raid1 --raid-devices=2 /dev/<device-a-partition> /dev/<device-b-partition>
  • 用 1 个设备分区创建降级的 raid1:
    • 创建降级的 raid1: mdadm --create /dev/md0 --level=raid1 --raid-devices=2 /dev/<device-a-partition> missing
    • 补上 raid1 的另一部分 mdadm --add /dev/md0 /dev/<device-b-partition>

raid10 创建:

  • 先创建 2 个 raid1:
    • mdadm --create /dev/md2 --level=raid1 --raid-devices=2 /dev/<device-a-partition> /dev/<device-b-partition>
    • mdadm --create /dev/md3 --level=raid1 --raid-devices=2 /dev/<device-c-partition> /dev/<device-d-partition>
  • 再用 2 个 raid1 创建一个 raid0:
    • mdadm --create /dev/md4 --level=raid0 --raid-devices=2 /dev/md{2,3}

raid5 创建: (最少需要 3 个设备,允许 1 个设备损坏)

  • 3 个工作设备和 1 个热备设备组 raid5:
    • mdadm --create -v /dev/md5 --level=raid5 --raid-devices=3 --spare-devices=1 /dev/<device-a-partition> /dev/<device-b-partition> /dev/<device-c-partition> /dev/<device-d-partition>
  • 将 1 个热备设备加入 raid5 使工作设备变成 4 个:
    • mdadm --grow /dev/md5 --raid-devices=4

raid6 创建: (最少需要 4 个设备,允许 2 个设备损坏)

  • 4 个工作设备和 1 个热备设备组 raid5:
    • mdadm --create -v /dev/md6 --level=raid6 --raid-devices=4 --spare-devices=1 /dev/<device-a-partition> /dev/<device-b-partition> /dev/<device-c-partition> /dev/<device-d-partition> /dev/<device-e-partition>
  • 将 1 个热备设备加入 raid6 使工作设备变成 5 个:
    • mdadm --grow /dev/md6 --raid-devices=5

创建完成之后,扫描所有的 raid 并把配置存入配置文件中:

  • RedHat: mdadm --detail --scan >> /etc/mdadm.conf
  • Debian: mdadm --detail --scan >> /etc/mdadm/mdadm.conf

cat /proc/mdstat 查看阵列状态。

mdadm --examine /dev/sda3 确认一个设备是否是 raid 的一部分。

raid 停止与激活:

  • mdadm -Ds > /etc/mdadm.conf 停止前一定要先保存 raid 信息到配置文件。
  • mdadm -S /dev/md5 停止阵列。
  • mdadm -As 激活所有阵列 (参考迁移 raid 章节)。

1.2. 销毁 raid

假设,现在需要销毁 /dev/md1 这个 raid array。现在它已经被取消挂载。

  1. mdadm --stop /dev/md1 停止这个阵列。
  2. /etc/mdadm.conf 中删除对应的配置行。
  3. mdadm --remove /dev/md1 删除 raid 设备。

如果第三条命令报错,说找不到要删除的设备,类似这样:

mdadm: error opening md1: No such file or directory

执行 mdadm --zero-superblock {/dev/<raid-device-a-partition> /dev/<raid-device-b-partition> ...} 直接删除设备分区上的超级块 (块里保存了 raid 信息)。

最后执行 cat /proc/mdstat 确认一下 /dev/md1 是否已经消失。

2. 维护 raid

编辑 /etc/mdadm/mdadm.conf 之后,要执行 sudo update-initramfs -u 才能让新的配置文件生效,如果有多个内核,执行 sudo update-initramfs -k all -u

2.1. 迁移 raid

2.1.1. mdadm.conf 文件还在

复制旧机器的 mdadm.conf 文件到新机器上,然后把旧机器上的挂载配置迁移到新机器上即可。

2.1.2. mdadm.conf 文件丢失

把旧 raid 设备导入新机器后,需要重新使用命令将所有设备组装成一个名为 /dev/md[0-127] 的虚拟设备。

然后执行 mdadm --detail --scan >> /etc/mdadm.conf (RedHat) 或者 mdadm --detail --scan >> /etc/mdadm/mdadm.conf (Debian) 重新生成配置文件。

如果不重新生成配置文件,那么在系统重启之后还要再重新组装一遍设备。

假设用了四个盘,需要执行以下命令:

mdadm --assemble --scan --verbose /dev/md<number> /dev/<device-a-partition> /dev/<device-b-partition> /dev/<device-c-partition> /dev/<device-d-partition>

2.2. raid 序号与名字

每个 raid array 都对应一个 /dev/md[0-127] 条目,只要 raid 存在,这个条目必然存在。

2.2.1. 更改 raid 设备序号

现有 raid1 设备 /dev/md127 要将其改为 /dev/md0。

  1. 移除 /dev/md127:
root@debian11:~# mdadm --stop /dev/md127
mdadm: stopped /dev/md127
  1. 用新序号重新组装 raid1:
# 如果 metadata 版本为 1.0 或更高版本,使用以下命令:
root@debian11:~# mdadm --assemble /dev/md0 /dev/sd{b,c}1
mdadm: /dev/md0 has been started with 2 drives.
# 如果 metadata 版本为 0.90 (这个版本的 mdadm 允许内核自动组装) 或者更早,使用以下命令:
root@debian11:~# mdadm --assemble /dev/md0 --update=super-minor /dev/sd[bc]1
  1. 最后 mdadm --detail --scan >> /etc/mdadm.conf (RedHat) 或者 mdadm --detail --scan >> /etc/mdadm/mdadm.conf (Debian) 保存配置。

2.2.2. 更改 raid name

现有 raid1 设备:

root@debian11:~# mdadm --detail --scan /dev/md0
ARRAY /dev/md0 metadata=1.2 name=debian11:0 UUID=3c59bf1a:aa2ed094:fe871a27:59f491b7
root@debian11:~# mdadm -D /dev/md0
/dev/md0:
           Version : 1.2
     Creation Time : Tue Oct 19 20:05:20 2021
        Raid Level : raid1
        Array Size : 14054400 (13.40 GiB 14.39 GB)
     Used Dev Size : 14054400 (13.40 GiB 14.39 GB)
      Raid Devices : 2
     Total Devices : 2
       Persistence : Superblock is persistent

       Update Time : Sun Mar 20 22:00:33 2022
             State : clean
    Active Devices : 2
   Working Devices : 2
    Failed Devices : 0
     Spare Devices : 0

Consistency Policy : resync

              Name : debian11:0  (local to host debian11)
              UUID : 3c59bf1a:aa2ed094:fe871a27:59f491b7
            Events : 299

    Number   Major   Minor   RaidDevice State
       0       8       97        0      active sync   /dev/sdg1
       2       8       81        1      active sync   /dev/sdf1

要将倒数第 7 行的 Name 改为 debian11:optane16ga

注: Name 值含义为 <homehost>:<name> 即前者为主机名 (/etc/hostname 里的值) 后者为 raid array 名称。

第一步,移除 /dev/md0:

root@debian11:~# mdadm --stop /dev/md0
mdadm: stopped /dev/md0

第二步,组装 raid1 时更新名称:

# 如果 metadata 版本为 1.0 或更高版本,使用以下命令:
root@debian11:~# mdadm --assemble /dev/md0 /dev/sd{b,c}1 --name=optane16ga --update=name
mdadm: /dev/md0 has been started with 2 drives.

最后一步 mdadm --detail --scan >> /etc/mdadm.conf (RedHat) 或者 mdadm --detail --scan >> /etc/mdadm/mdadm.conf (Debian) 保存配置。

2.3. 更换损坏的硬盘

现有 /dev/sd{b,c}1 组成的 raid1 设备 /dev/md0,现 /dev/sdb 设备已损坏,需要在保证 /dev/md0 正常运行的情况下,将 /dev/sdb 移出 raid。

  1. 将 /dev/sdb1 标记为 fail: mdadm --manage /dev/md0 --fail /dev/sdb1
root@debian11:~# mdadm --manage /dev/md0 --fail /dev/sdb1
mdadm: set /dev/sdb1 faulty in /dev/md0
root@debian11:~# cat /proc/mdstat
Personalities : [raid1]
md0 : active raid1 sdc1[2] sdb1[0](F)
      7813343232 blocks super 1.2 [2/1] [_U]
      bitmap: 0/59 pages [0KB], 65536KB chunk

unused devices: <none>
  1. 从 /dev/md0 中删除 /dev/sdb1: mdadm --manage /dev/md0 --remove /dev/sdb1
root@debian11:~# mdadm --manage /dev/md0 --remove /dev/sdb1
mdadm: hot removed /dev/sdb1 from /dev/md0
  1. 此时,从机器上拿下 /dev/sdb,换上新硬盘并分区。假设新硬盘同样为 /dev/sdb 其上分区同样为 /dev/sdb1。
  2. 将新硬盘加入到 raid 中:
root@debian11:~# mdadm --manage /dev/md0 --add /dev/sdb1
mdadm: re-added /dev/sdb1

到此,操作完成。剩下的只要等数据被同步到新硬盘上即可。

2.4. 清理 (scrub) raid array

/sys/block/md<num>/md/mismatch_cnt 文件记录了存在问题的块的数量。这个数字通常偏大,因为 mdadm 处理的最小单位是 page (一段连续的 block),mdadm 只知道哪个 page 有问题,所以这个数字偏大。

echo {check | repair | resync} > /sys/block/md<num>/md/sync_action 这三个操作分别对应 '检测错误','修复错误','重新同步' (突然断电或替换硬盘后需要)。

check 会让 mdadm 重新统计 mismatch_cnt 的值, repair, resync 这两个操作可能会让 mismatch_cnt 的值产生变化。

repair 操作对应的就是 mdadm scrub。但是一般不做这样的操作。因为 raid.wiki.kernel.org 说:

下面举个例子以证明 mdadm 在 raid1 中检测到数据不一致时,mdadm scrub 无法保证修复错误数据:

  1. mdadm 把主盘上损坏的数据返回给了 btrfs,btrfs 看见了主盘上损坏的 data extent
  2. 主盘是最先发生读写的盘,所以当负载较小时,btrfs 多数时候都能检测到 data extent corruption
  3. 但由于 btrfs 只看到一份 data extent 所以 btrfs 的 self-healing 无法生效
  4. mdadm 开始 scrub,把主盘上的有了问题的数据覆写到从盘上
  5. 此时数据彻底损坏,但 mdadm 报告修复成功

下面举个例子以证明 mdadm 在 raid5/6 中检测到数据不一致时,mdadm scrub 无法保证修复错误数据:

  1. raid5/6 中数据部分出现问题
  2. mdadm 根据错误数据重新计算校验和
  3. 原来校验和是对的,现在校验和也错了,但 mdadm 报告修复成功

以上两个例子都是 mdadm scrub 无法修复数据的情形。



Last Update: 2024-03-10 Sun 22:20

Generated by: Emacs 28.2 (Org mode 9.5.5)   Contact: lsz.sino@outlook.com

若正文中无特殊说明,本站内容遵循: 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议